static void GM_CDECL gmFileInfoOpGetDot(gmThread * a_thread, gmVariable * a_operands)
{
  gmUserObject * user = (gmUserObject *) GM_OBJECT(a_operands->m_value.m_ref);
  if(user && user->m_user)
  {
    gmFileInfoUser * fileInfo = (gmFileInfoUser *) user->m_user;
    gmStringObject * member = (gmStringObject *) GM_OBJECT(a_operands[1].m_value.m_ref);

    GM_ASSERT(sizeof(fileInfo->m_creationTime) <= sizeof(gmint));

    // NOTE: Not valid or tested for 64bit target

    if(strcmp(member->GetString(), "creationTime") == 0)
      a_operands->SetInt((gmint) fileInfo->m_creationTime);
    else if(strcmp(member->GetString(), "accessedTime") == 0)
      a_operands->SetInt((gmint) fileInfo->m_accessedTime);
    else if(strcmp(member->GetString(), "modifiedTime") == 0)
      a_operands->SetInt((gmint) fileInfo->m_modifiedTime);
    else if(strcmp(member->GetString(), "size") == 0)
      a_operands->SetInt((gmint) fileInfo->m_size);
    else
    {
      a_operands->Nullify();
      return;
    }
    return;
  }
  a_operands->Nullify();
}
Example #2
0
static int GM_CDECL gmfStringSpanExcluding(gmThread * a_thread)
{
  GM_CHECK_NUM_PARAMS(1);

  if(a_thread->ParamType(0) == GM_STRING)
  {
    const gmVariable * var = a_thread->GetThis();
  
    GM_ASSERT(var->m_type == GM_STRING);

    gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
    const char * thisStr = (const char *) *strObj;
    const char * otherStr = a_thread->ParamString(0);
    
    int offset = strcspn(thisStr, otherStr);
    char * buffer = (char *) alloca(offset + 1);
    memcpy(buffer, thisStr, offset);
    buffer[offset] = 0;

    a_thread->PushNewString(buffer, offset);

    return GM_OK;
  }

  return GM_EXCEPTION;
}
Example #3
0
// string string.SetAt(int a_index, int a_char);
// Returns string with modified character at offset, or original string if index out of range.
static int GM_CDECL gmStringSetAt(gmThread * a_thread)
{
  GM_CHECK_NUM_PARAMS(1);
  GM_CHECK_INT_PARAM(index, 0);
  GM_CHECK_INT_PARAM(newChar, 1);

  const gmVariable * var = a_thread->GetThis();

  GM_ASSERT(var->m_type == GM_STRING);

  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char * str = (const char *) *strObj;
  int strLength = strObj->GetLength();

  if(index < 0 || index >= strLength)
  {
    a_thread->PushString(strObj); //Return original string if index out of range
    return GM_OK;
  }

  char * buffer = (char *) alloca(strLength + 1); 
  memcpy(buffer, str, strLength + 1); //Copy old string
  buffer[index] = (char)newChar; //Set character in string

  a_thread->PushNewString(buffer, strLength);
  return GM_OK;
}
Example #4
0
static int GM_CDECL gmStringTrimRight(gmThread * a_thread)
{
  GM_STRING_PARAM(trim, 0, GM_WHITE_SPACE);

  const gmVariable * var = a_thread->GetThis();
  GM_ASSERT(var->m_type == GM_STRING);
  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char * str = (const char *) *strObj;
  int strLength = strObj->GetLength();
  if(strLength > 0)
  {
    char * buffer = (char *) alloca(strLength + 1);
    memcpy(buffer, str, strLength + 1); //Copy old string

    // Find beginning of trailing matches by starting at end
    char *lpsz = buffer + strLength;
    while (--lpsz >= buffer && strchr(trim, *lpsz) != NULL) {}
    ++lpsz;
    *lpsz = '\0';

    a_thread->PushNewString(buffer);
  }
  else
  {
    a_thread->PushString(strObj);
  }
  return GM_OK;
}
Example #5
0
static int GM_CDECL gmStringGetExtension(gmThread * a_thread)
{
  GM_INT_PARAM(keepDot, 0, 0);

  const gmVariable * var = a_thread->GetThis();
  GM_ASSERT(var->m_type == GM_STRING);
  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char * str = (const char *) *strObj;
  int strLength = strObj->GetLength();

  const char *lpsz = str + strLength;
  while (--lpsz >= str && *lpsz != '.') {}

  if(*lpsz == '.')
  {
    if(!keepDot)
    {
      ++lpsz;
    }
    a_thread->PushNewString(lpsz);
  }
  else
  {
    a_thread->PushNewString("");
  }
  return GM_OK;
}
Example #6
0
int GM_CDECL gmfToInt(gmThread * a_thread)
{
  const gmVariable * var = a_thread->GetThis();

  if(GM_INT == var->m_type)
  {
    a_thread->PushInt(var->m_value.m_int);
  }
  else if (GM_FLOAT == var->m_type)
  {
    a_thread->PushInt( (int)var->m_value.m_float);
  }
  else if (GM_STRING == var->m_type)
  {
    gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
    const char * cstr = * strObj;

    a_thread->PushInt( atoi(cstr) );
  }
  else
  {
    //a_thread->PushInt( 0 );
    return GM_EXCEPTION;
  }
  
  return GM_OK;
}
Example #7
0
int GM_CDECL gmfToString(gmThread * a_thread)
{
  const gmVariable * var = a_thread->GetThis();

  if(GM_INT == var->m_type)
  {
    char numberAsStringBuffer[64];
    sprintf(numberAsStringBuffer, "%d", var->m_value.m_int); // this won't be > 64 chars
    a_thread->PushNewString(numberAsStringBuffer);
  }
  else if (GM_FLOAT == var->m_type)
  {
    char numberAsStringBuffer[64];

    sprintf(numberAsStringBuffer, "%f", var->m_value.m_float); // this won't be > 64 chars

    a_thread->PushNewString(numberAsStringBuffer);
  }
  else if (GM_STRING == var->m_type)
  {
    a_thread->PushString( (gmStringObject *) GM_OBJECT(var->m_value.m_ref) );
  }
  else
  {
    return GM_EXCEPTION;
  }

  
  return GM_OK;
}
Example #8
0
static int GM_CDECL gmStringGetPath(gmThread * a_thread)
{
  GM_INT_PARAM(keepSlash, 0, 0);

  const gmVariable * var = a_thread->GetThis();
  GM_ASSERT(var->m_type == GM_STRING);
  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char * str = (const char *) *strObj;
  int strLength = strObj->GetLength();

  char * buffer = (char *) alloca(strLength + 1); 
  memcpy(buffer, str, strLength + 1); //Copy old string

  char *lpsz = buffer + strLength;
  while (--lpsz >= buffer && *lpsz != '\\' && *lpsz != '/') {}

  if(*lpsz == '\\' || *lpsz == '/')
  {
    if(keepSlash)
      lpsz[1] = 0;
    else
      lpsz[0] = 0;
    a_thread->PushNewString(buffer);
  }
  else
  {
    a_thread->PushNewString("");
  }
  return GM_OK;
}
Example #9
0
// int string.ReverseFind(char/string a_charOrStringToFind);
// Find the last instance of a specific character in a string.
// Returns character offset or -1 if not found.
static int GM_CDECL gmStringReverseFind(gmThread * a_thread)
{
  GM_CHECK_NUM_PARAMS(1);

  const char* retCharPtr = NULL;
  const gmVariable * var = a_thread->GetThis();
  GM_ASSERT(var->m_type == GM_STRING);
  gmStringObject * thisStrObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char* thisStr = (const char *) *thisStrObj;
  
  if(a_thread->ParamType(0) == GM_INT)
  {
    const char otherChar = (char)a_thread->ParamInt(0);
    
    //Find character
    retCharPtr = strrchr(thisStr, otherChar);
  }
  else if(a_thread->ParamType(0) == GM_STRING)
  {
    gmStringObject * otherStrObj = a_thread->ParamStringObject(0);
    const char* otherStr = a_thread->ParamString(0);

    //Find string
    const char* lastFoundPtr = NULL;
    const char* newTestPtr = NULL;
    const char* curTestPtr = thisStr;
    const char* endThisStr = thisStr + thisStrObj->GetLength();
    int searchStrLength = otherStrObj->GetLength();

    //Search through string for last occurence
    //Not very efficient, but very rarely used.
    for(;;)
    {
      newTestPtr = strstr(curTestPtr, otherStr);
      if(!newTestPtr)
      {
        break;
      }
      lastFoundPtr = newTestPtr;
      curTestPtr = newTestPtr + searchStrLength;
      if(curTestPtr > endThisStr)
      {
        break;
      }
    };

    retCharPtr = lastFoundPtr;
  }
  else
  {
    return GM_EXCEPTION;
  }

  // return -1 for not found, distance from beginning otherwise
  int retOffset = (retCharPtr == NULL) ? -1 : (int)(retCharPtr - thisStr);
  a_thread->PushInt(retOffset);

  return GM_OK;
}
Example #10
0
static int GM_CDECL gmfStringIsEmpty(gmThread * a_thread)
{
  const gmVariable * var = a_thread->GetThis();
  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);

  a_thread->PushInt( (strObj->GetLength() == 0) );
  
  return GM_OK;
}
Example #11
0
static void GM_CDECL gmFileFindOpGetDot(gmThread * a_thread, gmVariable * a_operands)
{
  gmUserObject * user = (gmUserObject *) GM_OBJECT(a_operands->m_value.m_ref);
  if(user && user->m_user)
  {
    gmFileFindUser * fileFind = (gmFileFindUser *) user->m_user;
    gmStringObject * member = (gmStringObject *) GM_OBJECT(a_operands[1].m_value.m_ref);

    if(strcmp(member->GetString(), "filename") == 0)
    {
      a_operands->SetString(a_thread->GetMachine()->AllocStringObject(fileFind->m_findData.cFileName));
      return;
    }
    else if(strcmp(member->GetString(), "size") == 0)
    {
      a_operands->SetInt(fileFind->m_findData.nFileSizeLow);
      return;
    }
  }
  a_operands->Nullify();
}
Example #12
0
static void GM_CDECL gmFileOpGetDot(gmThread * a_thread, gmVariable * a_operands)
{
  gmUserObject * user = (gmUserObject *) GM_OBJECT(a_operands->m_value.m_ref);
  if(user && user->m_user)
  {
    gmStringObject * member = (gmStringObject *) GM_OBJECT(a_operands[1].m_value.m_ref);

    if(strcmp(member->GetString(), "SEEK_CUR") == 0)
      a_operands->SetInt(SEEK_CUR);
    else if(strcmp(member->GetString(), "SEEK_END") == 0)
      a_operands->SetInt(SEEK_END);
    else if(strcmp(member->GetString(), "SEEK_SET") == 0)
      a_operands->SetInt(SEEK_SET);
    else
    {
      a_operands->Nullify();
      return;
    }
    return;
  }
  a_operands->Nullify();
}
Example #13
0
static int GM_CDECL gmStringGetFilename(gmThread * a_thread)
{
  const gmVariable * var = a_thread->GetThis();
  GM_ASSERT(var->m_type == GM_STRING);
  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char * str = (const char *) *strObj;
  int strLength = strObj->GetLength();

  const char *lpsz = str + strLength;
  while (--lpsz >= str && *lpsz != '\\' && *lpsz != '/') {}
  ++lpsz;

  a_thread->PushNewString(lpsz);
  return GM_OK;
}
Example #14
0
static int GM_CDECL gmStringTrimLeft(gmThread * a_thread)
{
  GM_STRING_PARAM(trim, 0, GM_WHITE_SPACE);

  const gmVariable * var = a_thread->GetThis();
  GM_ASSERT(var->m_type == GM_STRING);
  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char * str = (const char *) *strObj;
  if(strlen(str) > 0)
  {
    while(*str && strchr(trim, *str))
      ++str;
    a_thread->PushNewString(str);
  }
  else
    a_thread->PushString(strObj);
  return GM_OK;
}
Example #15
0
static int GM_CDECL gmfStringMid(gmThread * a_thread)
{
  GM_CHECK_NUM_PARAMS(2);

  int first = 0, count = 0;

  if(!gmGetFloatOrIntParamAsInt(a_thread, 0, first)) {return GM_EXCEPTION;}
  if(!gmGetFloatOrIntParamAsInt(a_thread, 1, count)) {return GM_EXCEPTION;}

  const gmVariable * var = a_thread->GetThis();
  
  GM_ASSERT(var->m_type == GM_STRING);

  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char * str = (const char *) *strObj;
  
  int length = strObj->GetLength();

  //Check bounds
  if (first < 0)
  {
    first = 0;
  }
  if (count < 0)
  {
    count = 0;
  }
  if (first + count > length)
  {
    count = length - first;
  }
  if (first > length)
  {
    count = 0;
  }

  char * buffer = (char *) alloca(count + 1);
  memcpy(buffer, str + first, count);
  buffer[count] = 0;

  a_thread->PushNewString(buffer);

  return GM_OK;
}
Example #16
0
// string.RemoveInvalidChars(a_replaceChar, a_invalidSet)
// eg. "File Name#1.tga".RemoveInvalidChars("_","# ") returns "File_Name_1.tga"
// Note: Parameters are optional.
static int GM_CDECL gmfStringReplaceCharsInSet(gmThread * a_thread)
{
  GM_INT_PARAM(repCharInt, 0, '_');
  GM_STRING_PARAM(invalidCharSet, 1, " \\/:-+");

  char repChar = (char)repCharInt; //Convert full int to char
  const gmVariable * varA = a_thread->GetThis();
  
  GM_ASSERT(varA->m_type == GM_STRING);

  gmStringObject * strObjA = (gmStringObject *) GM_OBJECT(varA->m_value.m_ref);
  const char* cStrA = strObjA->GetString();
  int lenA = strObjA->GetLength();

  //Alloc buffer on stack is fine, path strings cannot be long
  char * buffer = (char *) alloca(lenA + 1);
  memcpy(buffer, cStrA, lenA + 1);

  int validPos;

  //Check that replacement char is NOT in invalid set, otherwise endless loop...
  if(strchr(invalidCharSet, repChar))
  {
    return GM_EXCEPTION;
  }

  for(;;)
  {
    validPos = strcspn(buffer, invalidCharSet);
    if(validPos != lenA)
    {
      buffer[validPos] = repChar;
    }
    else
    {
      break;
    }
  }

  a_thread->PushNewString(buffer, lenA);
      
  return GM_OK;
}
Example #17
0
static int GM_CDECL gmfStringUpper(gmThread * a_thread)
{
  const gmVariable * var = a_thread->GetThis();
  
  GM_ASSERT(var->m_type == GM_STRING);

  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char * str = (const char *) *strObj;
  
  int length = strObj->GetLength();
  char * buffer = (char *) alloca(length + 1);
  memcpy(buffer, str, length + 1);
  
  strupr(buffer);

  a_thread->PushNewString(buffer, length);

  return GM_OK;
}
Example #18
0
static int GM_CDECL gmfStringCompareNoCase(gmThread * a_thread)
{
  GM_CHECK_NUM_PARAMS(1);

  if(a_thread->ParamType(0) == GM_STRING)
  {
    const gmVariable * var = a_thread->GetThis();
  
    GM_ASSERT(var->m_type == GM_STRING);

    gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
    const char* thisStr = (const char *) *strObj;
    const char* otherStr = a_thread->ParamString(0);

    a_thread->PushInt(_gmstricmp(thisStr, otherStr));
  
    return GM_OK;
  }

  return GM_EXCEPTION;
}
Example #19
0
// int string.GetAt(int a_index);
// Returns character at offset or null if index out of range.
static int GM_CDECL gmStringGetAt(gmThread * a_thread)
{
  GM_CHECK_NUM_PARAMS(1);
  GM_CHECK_INT_PARAM(index, 0);

  const gmVariable * var = a_thread->GetThis();

  GM_ASSERT(var->m_type == GM_STRING);

  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char * str = (const char *) *strObj;

  if(index < 0 || index >= strObj->GetLength())
  {
    a_thread->PushNull(); //Return null if index out of range
    return GM_OK;
  }

  a_thread->PushInt(str[index]);
  return GM_OK;
}
Example #20
0
static int GM_CDECL gmStringSetExtension(gmThread * a_thread)
{
  GM_STRING_PARAM(newExt, 0, "");

  const gmVariable * var = a_thread->GetThis();
  GM_ASSERT(var->m_type == GM_STRING);
  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);

  const char * str = (const char *) *strObj;
  int strLength = strObj->GetLength();
  int extLength = strlen(newExt);

  if (extLength && newExt[0] == '.')
  {
    ++newExt;
    extLength = strlen(newExt);
  }

  char *buffer = (char *) alloca(strLength + 1 + extLength);
  memcpy(buffer, str, strLength + 1);

  char *lpsz = buffer + strLength;
  while (--lpsz >= buffer && *lpsz != '.') {}

  if(*lpsz == '.')
  {
    *lpsz = '\0';
    if (extLength)
      sprintf(buffer, "%s.%s", buffer, newExt);

  }
  else if (extLength)
  {
    sprintf(buffer, "%s.%s", buffer, newExt);
  }

  a_thread->PushNewString(buffer);
  return GM_OK;
}
Example #21
0
// int string[int index]
// Note: Because strings are constant and in a table, it is impossible to implement SetInd.
static void GM_CDECL gmStringOpGetInd(gmThread * a_thread, gmVariable * a_operands)
{
  if( a_operands[0].m_type != GM_STRING ||
      a_operands[1].m_type != GM_INT )
  {
    a_operands->Nullify();
    return;
  }

  gmStringObject * strObjA = (gmStringObject *) GM_OBJECT(a_operands[0].m_value.m_ref);
  const char* cStrA = strObjA->GetString();
  int index = a_operands[1].m_value.m_int;
  
  if( index < 0 || index > strObjA->GetLength()-1 )
  {
    a_operands->Nullify();
  }
  else
  {
    a_operands->SetInt( (int)cStrA[index] );
  }
}
Example #22
0
static int GM_CDECL gmStringReverse(gmThread * a_thread)
{
  const gmVariable * var = a_thread->GetThis();
  GM_ASSERT(var->m_type == GM_STRING);
  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char * str = (const char *) *strObj;

  int len = strlen(str);
  if(len > 0)
  {
    char * buffer = (char *) alloca(len + 1); 
    memcpy(buffer, str, len + 1); //Copy old string

    while(len--)
    {
      buffer[len] = *(str++);
    }

    a_thread->PushNewString(buffer);
  }
  return GM_OK;
}
Example #23
0
static int GM_CDECL gmStringGetFilenameNoExt(gmThread * a_thread)
{
  const gmVariable * var = a_thread->GetThis();
  GM_ASSERT(var->m_type == GM_STRING);
  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char * str = (const char *) *strObj;
  int strLength = strObj->GetLength();

  char * buffer = (char *) alloca(strLength + 1);
  memcpy(buffer, str, strLength + 1); //Copy old string

  char *lpsz = buffer + strLength;
  while (--lpsz >= buffer && *lpsz != '\\' && *lpsz != '/') {}

  buffer = ++lpsz;
  strLength = strlen(buffer);
  lpsz = buffer + strLength;
  while (--lpsz >= buffer && *lpsz != '.') {}
  if(*lpsz == '.') *lpsz = 0;

  a_thread->PushNewString(buffer);
  return GM_OK;
}
Example #24
0
static int GM_CDECL gmfStringRightAt(gmThread * a_thread)
{
  GM_CHECK_NUM_PARAMS(1);
  GM_CHECK_INT_PARAM(index, 0);

  const gmVariable * var = a_thread->GetThis();
  
  GM_ASSERT(var->m_type == GM_STRING);

  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char * str = (const char *) *strObj;
  
  int length = strObj->GetLength();
  index = gmClamp(0, index, length);
  int count = (length - index);
  char * buffer = (char *) alloca(count + 1);
  memcpy(buffer, str + index, count);
  buffer[count] = 0;

  a_thread->PushNewString(buffer, count);

  return GM_OK;
}
Example #25
0
// int string.Find(char/string a_charOrStringToFind, int a_startOffset == 0);
// Find a character or character string in a string.
// Returns character offset or -1 if not found.
static int GM_CDECL gmStringFind(gmThread * a_thread)
{
  int numParams = GM_THREAD_ARG->GetNumParams();
  int startOffset = 0;
  char* retCharPtr = NULL;
  const gmVariable * var = a_thread->GetThis();
  GM_ASSERT(var->m_type == GM_STRING);
  gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref);
  const char* thisStr = (const char *) *strObj;
  
  if(numParams == 2)
  {
    if(a_thread->ParamType(1) == GM_INT)
    {
      startOffset = a_thread->ParamInt(1); //Optional start offset param
    }
    else
    {
      return GM_EXCEPTION;
    }
  } 
  else if(numParams < 1 || numParams > 2)
  {
    return GM_EXCEPTION;
  }

  //Check if this string is empty, or start offset out of range
  if( (strObj->GetLength() == 0) || 
      (startOffset > strObj->GetLength()) ||
      (startOffset < 0) 
    )
  {
    a_thread->PushInt( -1 ); //return Not Found
    return GM_OK;
  }

  if(a_thread->ParamType(0) == GM_INT)
  {
    const char otherChar = (char)a_thread->ParamInt(0);
    
    //Find character
    retCharPtr = (char*)strchr(thisStr + startOffset, otherChar);
  }
  else if(a_thread->ParamType(0) == GM_STRING)
  {
    const char* otherStr = a_thread->ParamString(0);

    //Find string
    retCharPtr = (char*)strstr(thisStr + startOffset, otherStr);
  }
  else
  {
    return GM_EXCEPTION;
  }

  // return -1 for not found, distance from beginning otherwise
  int retOffset = (retCharPtr == NULL) ? -1 : (int)(retCharPtr - thisStr);
  a_thread->PushInt(retOffset);

  return GM_OK;
}
Example #26
0
// string.AppendPath(a_appendString, a_endWithSlash);
// Append this string with another string, fixing for slashes
// a_endWithSlash is optional, default is false, removing trailing slashes.
static int GM_CDECL gmfStringAppendPath(gmThread * a_thread)
{
  //Need at least 1 parameter
  if(a_thread->GetNumParams() < 1)
  {
    return GM_EXCEPTION;
  }

  //Optional trailing slash flag
  int PutTrailingSlash = a_thread->ParamInt(1, false);

  if(a_thread->ParamType(0) == GM_STRING)
  {
    const gmVariable * varA = a_thread->GetThis();
  
    GM_ASSERT(varA->m_type == GM_STRING);

    gmStringObject * strObjA = (gmStringObject *) GM_OBJECT(varA->m_value.m_ref);
    gmStringObject * strObjB = a_thread->ParamStringObject(0);
    const char* cStrA = strObjA->GetString();
    const char* cStrB = strObjB->GetString();
    int lenA = strObjA->GetLength();
    int lenB = strObjB->GetLength();

    int curLength = lenA;
    int appLength = lenB;

    //Alloc buffer on stack is fine, path strings cannot be long
    char * buffer = (char *) alloca(curLength + appLength + 2);

    if(lenA > 0)
    {
      memcpy(buffer, cStrA, lenA);


      //Make sure first part has a slash
      if(buffer[curLength-1] != '\\' && buffer[curLength-1] != '/')
      {
        buffer[curLength] = '\\';
        curLength += 1;
      }
    }

    if(lenB > 0)
    {
      //Remove slash from start of append string
      const char* startOfAppend = cStrB;
      if((startOfAppend[0] == '\\') || (startOfAppend[0] == '/'))
      {
        startOfAppend += 1;
        appLength -= 1;
      }

      //Append the string
      memcpy(&buffer[curLength], startOfAppend, appLength);
    }

    int newLength = curLength + appLength;
  
    if(PutTrailingSlash && (newLength > 0)) //Only add slash if string is not empty
    {
      //Make sure path ends with slash
      if(buffer[newLength-1] != '\\' && buffer[newLength-1] != '/')
      {
        buffer[newLength] = '\\';
        newLength += 1;
      }
    }
    else
    {
      //Make sure path does not end with slash
      if(buffer[newLength-1] == '\\' || buffer[newLength-1] == '/')
      {
        newLength -= 1;
      }
    }

    //Make sure it is terminated
    buffer[newLength] = 0;

    a_thread->PushNewString(buffer, newLength);
  
    return GM_OK;
  }

  return GM_EXCEPTION;
}
Example #27
0
// string.AppendPath(a_appendString, a_endWithSlash);
// Append this string with another string, fixing for slashes
// a_endWithSlash is optional, default is false, removing trailing slashes.
static void GM_CDECL gmStringOpAppendPath(gmThread * a_thread, gmVariable * a_operands)
{
  // Both types must be strings
  if(a_operands[0].m_type != GM_STRING ||
     a_operands[1].m_type != GM_STRING)
  {
    a_operands[0].m_type = GM_NULL;
    a_operands[0].m_value.m_ref = 0;
    return;
  }

  gmStringObject * strObjA = (gmStringObject *) GM_OBJECT(a_operands[0].m_value.m_ref);
  gmStringObject * strObjB = (gmStringObject *) GM_OBJECT(a_operands[1].m_value.m_ref);
  const char* cStrA = strObjA->GetString();
  const char* cStrB = strObjB->GetString();
  int lenA = strObjA->GetLength();
  int lenB = strObjB->GetLength();

  int curLength = lenA;
  int appLength = lenB;

  //Alloc buffer on stack is fine, path strings cannot be long
  char * buffer = (char *) alloca(curLength + appLength + 2);

  if(lenA <= 0)
  {
    a_operands[0] = a_operands[1];
  }

  if(lenB <= 0)
  {
    return;
  }

  memcpy(buffer, cStrA, lenA);

  //Make sure first part has a slash
  if(buffer[curLength-1] != '\\' && buffer[curLength-1] != '/')
  {
    buffer[curLength] = '\\';
    curLength += 1;
  }

  //Remove slash from start of append string
  const char* startOfAppend = cStrB;
  if((startOfAppend[0] == '\\') || (startOfAppend[0] == '/'))
  {
    startOfAppend += 1;
    appLength -= 1;
  }

  //Append the string
  memcpy(&buffer[curLength], startOfAppend, appLength);

  int newLength = curLength + appLength;

  //Make sure it is terminated
  buffer[newLength] = 0;

  a_operands[0].m_type = GM_STRING;
  a_operands[0].m_value.m_ref = a_thread->GetMachine()->AllocStringObject(buffer, newLength)->GetRef();
}